﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Dubs_Finder.Model;
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading;
using System.Windows.Input;
using System.Windows;

namespace Dubs_Finder.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        private readonly IDataService _dataService;

        /// <summary>
        /// The <see cref="WelcomeTitle" /> property's name.
        /// </summary>
        public const string WelcomeTitlePropertyName = "WelcomeTitle";

        private string _welcomeTitle = string.Empty;

        /// <summary>
        /// Gets the WelcomeTitle property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string WelcomeTitle
        {
            get
            {
                return _welcomeTitle;
            }

            set
            {
                if (_welcomeTitle == value)
                {
                    return;
                }

                _welcomeTitle = value;
                RaisePropertyChanged(WelcomeTitlePropertyName);
            }
        }


        public ICommand ClickCommand { get; private set; }
        public ICommand PauseCommand { get; private set; }
        public ICommand AbortCommand { get; private set; }

        public ObservableCollection<DubsWrapper> DubsWrapper { get; private set; }

        private ObservableCollection<FileWrapper> selectedDub;
        public ObservableCollection<FileWrapper> SelectedDub { get { return selectedDub; } internal set { selectedDub = value; RaisePropertyChanged("SelectedDub"); } }

        public MainModel model;
        private Thread runnerThread;

        public DubsWrapper SelectedDubsWrapper { private get; set; }

        private bool runnerIsPaused = false;
        internal bool runAsync { get; set; }
        internal bool runRecursive { get; set; }

        private int totalFiles = 1;
        public int TotalFiles { get { return totalFiles; } private set { totalFiles = value; RaisePropertyChanged("TotalFiles"); } }
        private int scannedFiles = 0;
        public int ScannedFiles { get { return this.scannedFiles; } private set { scannedFiles = value; RaisePropertyChanged("ScannedFiles"); } }

        private string statusBarMouseOverHint = "Empty"; 
        public string StatusBarMouseOverHint { get { return statusBarMouseOverHint; } set {statusBarMouseOverHint = value; RaisePropertyChanged("StatusBarMouseOverHint"); } }
        private string statusBarStatusHint = "Empty";
        public string StatusBarStatusHint { get { return statusBarStatusHint; } set { statusBarStatusHint = value; RaisePropertyChanged("StatusBarStatusHint"); } }


        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        /// 
        public MainViewModel(IDataService dataService)
        {
            _dataService = dataService;
            _dataService.GetData(
                (item, error) =>
                {
                    if (error != null)
                    {
                        // Report error here
                        return;
                    }

                    WelcomeTitle = item.Title;
                });

            ClickCommand = new RelayCommand(Click, canClick);
            PauseCommand = new RelayCommand(Pause, canPause);
            AbortCommand = new RelayCommand(Abort, canAbort);

            model = new MainModel();
            this.DubsWrapper = model.dw;
            runnerThread = new Thread(model.main);
        }

        ////public override void Cleanup()
        ////{
        ////    // Clean up if needed

        ////    base.Cleanup();
        ////}

        internal void OpenLocation(FileWrapper selectedFile)
        {
            Process exporerWindowProcess = new Process();
            exporerWindowProcess.StartInfo.FileName = "explorer.exe";
            exporerWindowProcess.StartInfo.Arguments = "/select, \"" + selectedFile.Path;
            exporerWindowProcess.Start();
        }

        internal void MarkFile(FileWrapper selectedFile)
        {
            SelectedDubsWrapper.MainFile = selectedFile;
        }

        internal void DeleteFile(FileWrapper selectedFile)
        {
            Debug.WriteLine("Delete right-clicked file dummy");
        }

        internal void setAllDubs(bool value)
        {
            foreach (DubsWrapper dw in this.DubsWrapper)
            {
                dw.IsChecked = value;
            }
        }

        private bool canClick()
        {
            return (runnerThread != null && !runnerThread.IsAlive);
        }

        private void Click()
        {
            this.TotalFiles = 1;
            this.ScannedFiles = 0;
            model.CleanUp();
            runnerThread = new Thread(model.main);
            if (model.GetDirectory() && !runnerThread.IsAlive)
            {
                this.TotalFiles = model.GetTotalFiles();
                this.StatusBarMouseOverHint = "Empty";
                this.StatusBarStatusHint = this.TotalFiles.ToString();
                this.model.ParseScannedCounter(this.updateCounter);
                this.model.ParseStateText(this.updateState);

                runnerThread.Start();
                runnerThread.IsBackground = true;

                /*for (int i = 0; i < 10; i++)
                {
                    writeScanned();
                    Thread.Sleep(100);
                }*/
            }
        }

        private bool canPause()
        {
            return runnerThread.IsAlive;
        }

        private void Pause()
        {
            if (!runnerIsPaused)
            {
                runnerThread.Suspend();
                runnerIsPaused = true;
            }
            else 
            {
                runnerThread.Resume();
                runnerIsPaused = false;
            }
            this.StatusBarMouseOverHint = ScannedFiles.ToString();
            Debug.WriteLine("Read {0} of {1} files", ScannedFiles, TotalFiles);
        }

        private bool canAbort()
        {
            return runnerThread.ThreadState.Equals(System.Threading.ThreadState.Background);
        }

        private void Abort()
        {
            runnerThread.Abort();
        }

        private void writeScanned()
        {
            Debug.WriteLine("ScannedFiles: {0}", ScannedFiles);
            this.StatusBarMouseOverHint = ScannedFiles.ToString();
        }

        private void updateCounter(int count)
        {
            this.ScannedFiles = count;
        }

        private void updateState(string state)
        {
            this.StatusBarStatusHint = state;
        }
    }
}